#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include "LoopQueue.hpp"
#include "Task.h"
using namespace std;

string selfThreadName() {
    char buffer[128] = {};
    snprintf(buffer, sizeof buffer, "thread[0X%x]", pthread_self());
    return string(buffer);
}

void* producer(void* lq) {
    LoopQueue<Task>* loop_queue = static_cast<LoopQueue<Task>*>(lq);

    while (true) {
        int x = rand() % 101;
        int y = rand() % 21;
        Task task(x, y, operators[rand() % operators.size()], calculate);
        cout << selfThreadName() << ", 生产者派发了一个任务 " << task.showTask() << endl;
        loop_queue->push(move(task));

        sleep(1);
    }
}

void* consumer(void* lq) {
    LoopQueue<Task>* loop_queue = static_cast<LoopQueue<Task>*>(lq);

    while (true) {
        Task task;
        loop_queue->pop(&task);

        cout << selfThreadName() << ", 消费者处理了一个任务 " << task() << endl;
    }
}

int main() {
    srand(static_cast<unsigned int>(time(nullptr)) ^ getpid() & pthread_self());
    
    LoopQueue<Task>* loop_queue = new LoopQueue<Task>();

    pthread_t producer_threads[3], calculate_threads[5];

    for (auto& producer_thread : producer_threads) {
        pthread_create(&producer_thread, nullptr, producer, (void*)loop_queue);
    }

    for (auto& calculate_thread : calculate_threads) {
        pthread_create(&calculate_thread, nullptr, consumer, (void*)loop_queue);
    }


    for (auto& producer_thread : producer_threads) {
        pthread_join(producer_thread, nullptr);
    }

    for (auto& calculate_thread : calculate_threads) {
        pthread_join(calculate_thread, nullptr);
    }

    delete loop_queue;
    return 0;
}